const jwt = require('jsonwebtoken')
const db = require('../libs/db')
const User = db.model('user')

const secretKey = '123456'
const expiresIn = '2h'
const tokenQueryField = 'token'


function JwtAuth () {}

JwtAuth.prototype.initialize = function () {
  var that = this
  return async (ctx, next) => {
    var result = null
    var decoded = null
    var token = ctx.headers['authorization']
    if (token) {
      if (!(/Bearer .*?/.test(token))) {
        result = {
          bool: false,
          msg: 'Authorization Error !'
        }
      } else {
        token = token.replace('Bearer ', '')
      }
    } else {
      token = ctx.query[tokenQueryField]
    }
    if (!token) {
      result = {
        bool: false,
        msg: 'Authorization token not found !'
      }
    } else {
      try {
        decoded = jwt.verify(token, secretKey)
      } catch(err) {
        result = {
          bool: false,
          msg: 'Token validation fails, has expired'
        }
      }
    }
    
    ctx.state.token = token
    ctx.state.auth = decoded
    ctx.state.tokenErr = result

    ctx.user = async () => {
      if (!ctx.auth()) return null
      var id = ctx.state.auth.id
      return await User.findOne({where: {id}})
    }
    ctx.auth = () => {
      return !!ctx.state.auth
    }
    ctx.login = that.login
    await next()
  }
}

JwtAuth.prototype.authenticate = () => {
  return async (ctx, next) => {
    if (ctx.state.tokenErr) {
      ctx.status = 401
      ctx.body = ctx.state.tokenErr
      return false
    }
    if (!ctx.state.auth) {
      ctx.body = {
        bool: false,
        msg: 'the token auth was not found !'
      }
      return false
    }
    await next()
  }
}

JwtAuth.prototype.login = (user) => {
  if (!(user instanceof User)) return null
  var token = jwt.sign({id: user.id}, secretKey, {expiresIn})
  return token
}

module.exports = new JwtAuth()
